#ifndef __NUC_CLK_H__
#define __NUC_CLK_H__

#include "nuc970.h"

#define REG_BITS_SET(reg,pos,msk,val) outpw(reg,(inpw(reg)&(~(((uint32_t)(msk))<<(pos))))|((((uint32_t)(val))<<(pos)))))
#define REG_BITS_GET(reg,pos,num)     ((inpw(reg) >> (pos))&(~(((0xFFFFFFFFUL>>(32-num))))))
#define REG_BIT_SET(reg,pos)          outpw(reg,inpw(reg)|(1UL<<pos))
#define REG_BIT_CLR(reg,pos)          outpw(reg,inpw(reg)&(~(1UL<<pos)))
#define REG_BIT_GET(reg,pos)          ((inpw(reg)>>pos)&0x01UL)

//CLK_DIVCTL4
#define CLK_UART3_N(x)           REG_BITS_SET(REG_CLK_DIVCTL4, 29 ,0x07UL, (x-1)) //x=1..8
#define CLK_UART3_S_XIN()        outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<27))) | (0UL<<27))
#define CLK_UART3_S_ACLK()       outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<27))) | (2UL<<27))      
#define CLK_UART3_S_UCLK()       outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<27))) | (3UL<<27))       
#define CLK_UART3_SDIV(x)        outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(7UL<<24))) | (((uint32_t)(x-1))<<24)) //x=1..8

#define CLK_UART2_N(x)            REG_BITS_SET(REG_CLK_DIVCTL4, 21 ,0x07UL, (x-1)) //x=1..8
#define CLK_UART2_S_XIN()        outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<19))) | (0UL<<19))
#define CLK_UART2_S_ACLK()       outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<19))) | (2UL<<19))      
#define CLK_UART2_S_UCLK()       outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<19))) | (3UL<<19))       
#define CLK_UART2_SDIV(x)        outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(7UL<<16))) | (((uint32_t)(x-1))<<16)) //x=1..8

#define CLK_UART1_N(x)            REG_BITS_SET(REG_CLK_DIVCTL4, 13 ,0x07UL, (x-1)) //x=1..8
#define CLK_UART1_S_XIN()        outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<11))) | (0UL<<11))
#define CLK_UART1_S_ACLK()       outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<11))) | (2UL<<11))      
#define CLK_UART1_S_UCLK()       outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<11))) | (3UL<<11))       
#define CLK_UART1_SDIV(x)        outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(7UL<<8))) | (((uint32_t)(x-1))<<8)) //x=1..8

#define CLK_UART0_N(x)            REG_BITS_SET(REG_CLK_DIVCTL4, 5 ,0x07UL, (x-1)) //x=1..8
#define CLK_UART0_S_XIN()        outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<3))) | (0UL<<3))
#define CLK_UART0_S_ACLK()       outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<3))) | (2UL<<3))      
#define CLK_UART0_S_UCLK()       outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(3UL<<3))) | (3UL<<3))       
#define CLK_UART0_SDIV(x)        outpw(REG_CLK_DIVCTL4,(inpw(REG_CLK_DIVCTL4) & (~(7UL<<0))) | (((uint32_t)(x-1))<<0)) //x=1..8

//CLK_DIVCTL5
#define CLK_UART7_N(x)            REG_BITS_SET(REG_CLK_DIVCTL5, 29 ,0x07UL, (x-1)) //x=1..8
#define CLK_UART7_S_XIN()        outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<27))) | (0UL<<27))
#define CLK_UART7_S_ACLK()       outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<27))) | (2UL<<27))      
#define CLK_UART7_S_UCLK()       outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<27))) | (3UL<<27))       
#define CLK_UART7_SDIV(x)        outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(7UL<<24))) | (((uint32_t)(x-1))<<24)) //x=1..8

#define CLK_UART6_N(x)            REG_BITS_SET(REG_CLK_DIVCTL5, 21 ,0x07UL, (x-1)) //x=1..8
#define CLK_UART6_S_XIN()        outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<19))) | (0UL<<19))
#define CLK_UART6_S_ACLK()       outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<19))) | (2UL<<19))      
#define CLK_UART6_S_UCLK()       outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<19))) | (3UL<<19))       
#define CLK_UART6_SDIV(x)        outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(7UL<<16))) | (((uint32_t)(x-1))<<16)) //x=1..8

#define CLK_UART5_N(x)            REG_BITS_SET(REG_CLK_DIVCTL5, 13 ,0x07UL, (x-1)) //x=1..8
#define CLK_UART5_S_XIN()        outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<11))) | (0UL<<11))
#define CLK_UART5_S_ACLK()       outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<11))) | (2UL<<11))      
#define CLK_UART5_S_UCLK()       outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<11))) | (3UL<<11))       
#define CLK_UART5_SDIV(x)        outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(7UL<<8))) | (((uint32_t)(x-1))<<8)) //x=1..8

#define CLK_UART4_N(x)            REG_BITS_SET(REG_CLK_DIVCTL5, 5 ,0x07UL, (x-1)) //x=1..8
#define CLK_UART4_S_XIN()        outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<3))) | (0UL<<3))
#define CLK_UART4_S_ACLK()       outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<3))) | (2UL<<3))      
#define CLK_UART4_S_UCLK()       outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(3UL<<3))) | (3UL<<3))       
#define CLK_UART4_SDIV(x)        outpw(REG_CLK_DIVCTL5,(inpw(REG_CLK_DIVCTL5) & (~(7UL<<0))) | (((uint32_t)(x-1))<<0)) //x=1..8

//CLK_DIVCTL6
#define CLK_SMC1_N(x)           outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(15UL<<28))) | (((uint32_t)(x-1))<<28)) //x=1..16
#define CLK_SMC0_N(x)           outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(15UL<<24))) | (((uint32_t)(x-1))<<24)) //x=1..16

#define CLK_UART10_N(x)           outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(7UL<<21))) | (((uint32_t)(x-1))<<21)) //x=1..8
#define CLK_UART10_S_XIN()        outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(3UL<<19))) | (0UL<<19))
#define CLK_UART10_S_ACLK()       outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(3UL<<19))) | (2UL<<19))      
#define CLK_UART10_S_UCLK()       outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(3UL<<19))) | (3UL<<19))       
#define CLK_UART10_SDIV(x)        outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(7UL<<16))) | (((uint32_t)(x-1))<<16)) //x=1..8

#define CLK_UART9_N(x)           outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(7UL<<13))) | (((uint32_t)(x-1))<<13)) //x=1..8
#define CLK_UART9_S_XIN()        outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(3UL<<11))) | (0UL<<11))
#define CLK_UART9_S_ACLK()       outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(3UL<<11))) | (2UL<<11))      
#define CLK_UART9_S_UCLK()       outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(3UL<<11))) | (3UL<<11))       
#define CLK_UART9_SDIV(x)        outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(7UL<<8))) | (((uint32_t)(x-1))<<8)) //x=1..8

#define CLK_UART8_N(x)           outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(7UL<<5))) | (((uint32_t)(x-1))<<5)) //x=1..8
#define CLK_UART8_S_XIN()        outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(3UL<<3))) | (0UL<<3))
#define CLK_UART8_S_ACLK()       outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(3UL<<3))) | (2UL<<3))      
#define CLK_UART8_S_UCLK()       outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(3UL<<3))) | (3UL<<3))       
#define CLK_UART8_SDIV(x)        outpw(REG_CLK_DIVCTL6,(inpw(REG_CLK_DIVCTL6) & (~(7UL<<0))) | (((uint32_t)(x-1))<<0)) //x=1..8

//CLK_DIVCTL7
#define CLK_ADC_N(x)           outpw(REG_CLK_DIVCTL7,(inpw(REG_CLK_DIVCTL7) & (~(255UL<<24))) | (((uint32_t)(x-1))<<24)) //x=1..256
#define CLK_ADC_S_XIN()        outpw(REG_CLK_DIVCTL7,(inpw(REG_CLK_DIVCTL7) & (~(3UL<<19))) | (0UL<<19))
#define CLK_ADC_S_ACLK()       outpw(REG_CLK_DIVCTL7,(inpw(REG_CLK_DIVCTL7) & (~(3UL<<19))) | (2UL<<19))      
#define CLK_ADC_S_UCLK()       outpw(REG_CLK_DIVCTL7,(inpw(REG_CLK_DIVCTL7) & (~(3UL<<19))) | (3UL<<19))       
#define CLK_ADC_SDIV(x)        outpw(REG_CLK_DIVCTL7,(inpw(REG_CLK_DIVCTL7) & (~(7UL<<16))) | (((uint32_t)(x-1))<<16)) //x=1..8

#define CLK_GPIO_S_XIN()        outpw(REG_CLK_DIVCTL7,(inpw(REG_CLK_DIVCTL7) & (~(1UL<<7))))
#define CLK_GPIO_S_X32()        outpw(REG_CLK_DIVCTL7,(inpw(REG_CLK_DIVCTL7) | ((1UL<<7))))
#define CLK_GPIO_N(x)           outpw(REG_CLK_DIVCTL7,(inpw(REG_CLK_DIVCTL7) & (~(127UL<<0))) | (((uint32_t)(x-1))<<0)) //x=1..128

//CLK_DIVCTL8
#define CLK_S_ETIMER3_POS   28
#define CLK_S_ETIMER2_POS   24
#define CLK_S_ETIMER1_POS   20
#define CLK_S_ETIMER0_POS   16
#define CLK_S_WWDT_POS   12
#define CLK_S_WDT_POS   8
#define CLK_S_MII_POS   0
#define CLK8_SEL(pos,val)             outpw(REG_CLK_DIVCTL8,(inpw(REG_CLK_DIVCTL8) & (~(3UL<<pos))) | ((uint32_t)(val)<<pos))

#define CLK_ETIMER0_S_XIN()           CLK8_SEL(CLK_S_ETIMER0_POS, 0UL)
#define CLK_ETIMER0_S_PCLK()          CLK8_SEL(CLK_S_ETIMER0_POS, 1UL)
#define CLK_ETIMER0_S_PCKL_DIV4096()  CLK8_SEL(CLK_S_ETIMER0_POS, 2UL)
#define CLK_ETIMER0_S_X32()           CLK8_SEL(CLK_S_ETIMER0_POS, 3UL)
#define CLK_ETIMER1_S_XIN()           CLK8_SEL(CLK_S_ETIMER1_POS, 0UL)
#define CLK_ETIMER1_S_PCLK()          CLK8_SEL(CLK_S_ETIMER1_POS, 1UL)
#define CLK_ETIMER1_S_PCKL_DIV4096()  CLK8_SEL(CLK_S_ETIMER1_POS, 2UL)
#define CLK_ETIMER1_S_X32()           CLK8_SEL(CLK_S_ETIMER1_POS, 3UL)
#define CLK_ETIMER2_S_XIN()           CLK8_SEL(CLK_S_ETIMER2_POS, 0UL)
#define CLK_ETIMER2_S_PCLK()          CLK8_SEL(CLK_S_ETIMER2_POS, 1UL)
#define CLK_ETIMER2_S_PCKL_DIV4096()  CLK8_SEL(CLK_S_ETIMER2_POS, 2UL)
#define CLK_ETIMER2_S_X32()           CLK8_SEL(CLK_S_ETIMER2_POS, 3UL)
#define CLK_ETIMER3_S_XIN()           CLK8_SEL(CLK_S_ETIMER3_POS, 0UL)
#define CLK_ETIMER3_S_PCLK()          CLK8_SEL(CLK_S_ETIMER3_POS, 1UL)
#define CLK_ETIMER3_S_PCKL_DIV4096()  CLK8_SEL(CLK_S_ETIMER3_POS, 2UL)
#define CLK_ETIMER3_S_X32()           CLK8_SEL(CLK_S_ETIMER3_POS, 3UL)
#define CLK_WWDT_S_XIN()              CLK8_SEL(CLK_S_WWDT_POS, 0UL)
#define CLK_WWDT_S_XIN_DIV128()       CLK8_SEL(CLK_S_WWDT_POS, 1UL)
#define CLK_WWDT_S_PCKL_DIV4096()     CLK8_SEL(CLK_S_WWDT_POS, 2UL)
#define CLK_WWDT_S_X32()              CLK8_SEL(CLK_S_WWDT_POS, 3UL)
#define CLK_WDT_S_XIN()               CLK8_SEL(CLK_S_WDT_POS, 0UL)
#define CLK_WDT_S_XIN_DIV128()        CLK8_SEL(CLK_S_WDT_POS, 1UL)
#define CLK_WDT_S_PCKL_DIV4096()      CLK8_SEL(CLK_S_WDT_POS, 2UL)
#define CLK_WDT_S_X32()               CLK8_SEL(CLK_S_WDT_POS, 3UL)

#endif
